//
//  iFly.m
//  Runner
//
//  Created by sunxy on 2019/6/26.
//  Copyright © 2019 The Chromium Authors. All rights reserved.
//

#import "iFly.h"

#import "IFlyMSC/IFlyMSC.h"
#import "Definition.h"





@interface iFly() <IFlySpeechEvaluatorDelegate ,IFlyPcmRecorderDelegate>

@property (nonatomic, strong) IFlySpeechEvaluator *iFlySpeechEvaluator;
@property (nonatomic, assign) BOOL isSessionResultAppear;
@property (nonatomic, assign) BOOL isSessionEnd;
@property (nonatomic, assign) NSString* audioFileURL;
@property (nonatomic, assign) BOOL isValidInput;
@property (nonatomic, assign) BOOL isDidset;
@property (nonatomic,strong) IFlyPcmRecorder *pcmRecorder;//PCM Recorder to be used to demonstrate Audio Stream Evaluation.
@property (nonatomic,assign) BOOL isBeginOfSpeech;//Whether or not SDK has invoke the delegate methods of beginOfSpeech.

@property (nonatomic, strong) completionHandler completionHandlers; // array of completionHandler objects.

@end

@implementation iFly


- (void)initIse {
    // 获取评测对象单例
    _iFlySpeechEvaluator = [IFlySpeechEvaluator sharedInstance];
    _iFlySpeechEvaluator.delegate = self;
    // 设置训练参数
    // 清空参数
    [_iFlySpeechEvaluator setParameter:@"" forKey:[IFlySpeechConstant PARAMS]];
    // 设置评测采样率
    [self.iFlySpeechEvaluator setParameter:@"16000" forKey:[IFlySpeechConstant SAMPLE_RATE]];
    // 设置评测题目编码，如果是utf-8格式，请添加bom头，添加方式可参考demo。
    [self.iFlySpeechEvaluator setParameter:@"utf-8" forKey:[IFlySpeechConstant TEXT_ENCODING]];
    // 设置评测题目结果格式，目前仅支持xml
    [self.iFlySpeechEvaluator setParameter:@"xml" forKey:[IFlySpeechConstant ISE_RESULT_TYPE]];
    // 设置评测前端点超时
    [self.iFlySpeechEvaluator setParameter:@"5000" forKey:[IFlySpeechConstant VAD_BOS]];
    // 设置评测后端点超时
    [self.iFlySpeechEvaluator setParameter:@"1800" forKey:[IFlySpeechConstant VAD_EOS]];
    // 设置评测题型
    [self.iFlySpeechEvaluator setParameter:@"read_sentence" forKey:[IFlySpeechConstant ISE_CATEGORY]];
    // 设置评测语言
    [self.iFlySpeechEvaluator setParameter:@"en_us"
                                    forKey:[IFlySpeechConstant LANGUAGE]];
    // 设置评测结果级别
    [self.iFlySpeechEvaluator setParameter:@"complete" forKey:[IFlySpeechConstant ISE_RESULT_LEVEL]];
    // 设置评测超时
    [self.iFlySpeechEvaluator setParameter:@"-1" forKey:[IFlySpeechConstant SPEECH_TIMEOUT]];
    
    
    //    //Initialize recorder
    if (_pcmRecorder == nil)
    {
        _pcmRecorder = [IFlyPcmRecorder sharedInstance];
    }
    _pcmRecorder.delegate = self;
    [_pcmRecorder setSample:@"16000"];
    
    
    //    NSString * path = [NSTemporaryDirectory() stringByAppendingString:@"sounddd.pcm"];
    [_pcmRecorder setSaveAudioPath:nil];
    
}


-(void) recognizeWithAudio:(NSString*)sourceText :(NSString*)_pcmFilePath{
    
    //设置音频源为音频流（-1）
    [self.iFlySpeechEvaluator setParameter:@"-1" forKey:@"audio_source"];
    
    NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
    
    NSLog(@"text encoding:%@",[self.iFlySpeechEvaluator parameterForKey:[IFlySpeechConstant TEXT_ENCODING]]);
    NSLog(@"language:%@",[self.iFlySpeechEvaluator parameterForKey:[IFlySpeechConstant LANGUAGE]]);
    
    NSMutableData *buffer = nil;
    
    buffer= [NSMutableData dataWithData:[sourceText dataUsingEncoding:encoding]];
    //启动评测服务
    [self.iFlySpeechEvaluator startListening:buffer params:nil];
    //写入音频数据
    NSData *data = [NSData dataWithContentsOfFile:_pcmFilePath];    //从文件中读取音频
    NSLog(@"data lenght path=%@",_pcmFilePath);
    NSLog(@"data lenght=%lu",data.length);
    [self.iFlySpeechEvaluator writeAudio:data];//写入音频，让SDK评测。建议将音频数据分段写入。
    //音频写入结束或出错时，必须调用结束评测接口
    [self.iFlySpeechEvaluator stopListening];//音频数据写入完成，进入等待状态
}


/*!
 *  start recorder
 */
- (void)startRecord:(NSString*)sourceText{
    //    NSString* sourceText=@"The quick brown fox jumps over the lazy dog.";
    
    NSLog(@"%s[IN]",__func__);
    
    NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
    
    NSLog(@"text encoding:%@",[self.iFlySpeechEvaluator parameterForKey:[IFlySpeechConstant TEXT_ENCODING]]);
    NSLog(@"language:%@",[self.iFlySpeechEvaluator parameterForKey:[IFlySpeechConstant LANGUAGE]]);
    
    NSMutableData *buffer = nil;
    
    buffer= [NSMutableData dataWithData:[sourceText dataUsingEncoding:encoding]];
    NSLog(@" \nen buffer length: %lu",(unsigned long)[buffer length]);
    
    NSLog(@"begin result=%@",NSLocalizedString(@"M_ISE_Noti2", nil));
    
    
    BOOL ret = [self.iFlySpeechEvaluator startListening:buffer params:nil];
    
    if(ret){
        
        
        //Set audio stream as audio source,which requires the developer import audio data into the recognition control by self through "writeAudio:".
        if ([self.iseParams.audioSource isEqualToString:IFLY_AUDIO_SOURCE_STREAM]){
            
            _isBeginOfSpeech = NO;
            //set the category of AVAudioSession
            [IFlyAudioSession initRecordingAudioSession];
            
            _pcmRecorder.delegate = self;
            
            //start recording
            BOOL ret = [_pcmRecorder start];
            
            NSLog(@"%s[OUT],Success,Recorder ret=%d",__func__,ret);
        }
    }
}

/*!
 *  stop recording
 */
- (void)stopRecord {
    if ([self.iseParams.audioSource isEqualToString:IFLY_AUDIO_SOURCE_STREAM] && !_isBeginOfSpeech){
        NSLog(@"%s,stop recording",__func__);
        [_pcmRecorder stop];
    }
    NSLog(@"stopListeningggggg");
    [self.iFlySpeechEvaluator stopListening];
}

-(void )cancel{
    [self.iFlySpeechEvaluator cancel];
    self.iFlySpeechEvaluator.delegate = nil;
    
    [_pcmRecorder stop];
    _pcmRecorder.delegate = nil;
}



-(void)setExclusiveTouchForButtons:(UIView *)myView
{
    for (UIView * button in [myView subviews]) {
        if([button isKindOfClass:[UIButton class]])
        {
            [((UIButton *)button) setExclusiveTouch:YES];
        }
        else if ([button isKindOfClass:[UIView class]])
        {
            [self setExclusiveTouchForButtons:button];
        }
    }
}









#pragma mark - ISESettingDelegate

/*!
 *  callback of ISE setting
 */
- (void)onParamsChanged:(ISEParams *)params {
    self.iseParams=params;
}

#pragma mark - IFlySpeechEvaluatorDelegate

/*!
 *  volume callback,range from 0 to 30.
 */
- (void)onVolumeChanged:(int)volume buffer:(NSData *)buffer {
    //    NSLog(@"volume:%d",volume);
    //    [self.popupView setText:[NSString stringWithFormat:@"%@：%d", NSLocalizedString(@"T_RecVol", nil),volume]];
    //    [self.view addSubview:self.popupView];
}

/*!
 *  Beginning Of Speech
 */
- (void)onBeginOfSpeech {
    
    if ([self.iseParams.audioSource isEqualToString:IFLY_AUDIO_SOURCE_STREAM]){
        _isBeginOfSpeech =YES;
    }
    
}

/*!
 *  End Of Speech
 */
- (void)onEndOfSpeech {
    
    if ([self.iseParams.audioSource isEqualToString:IFLY_AUDIO_SOURCE_STREAM]){
        [_pcmRecorder stop];
    }
    
}

/*!
 *  callback of canceling evaluation
 */
- (void)onCancel {
    
}

/*!
 *  evaluation session completion, which will be invoked no matter whether it exits error.
 *  error.errorCode =
 *  0     success
 *  other fail
 */
- (void)onCompleted:(IFlySpeechError *)errorCode {
    if(errorCode && errorCode.errorCode!=0){
        NSLog(@"errrrrrrrror code=%d",errorCode.errorCode);
    }
}

/*!
 *  result callback of speech evaluation
 *  results：evaluation results
 *  isLast：whether or not this is the last result
 */
- (void)onResults:(NSData *)results isLast:(BOOL)isLast{
    if (results) {
        NSString *showText = @"";
        
        const char* chResult=[results bytes];
        
        BOOL isUTF8=[[self.iFlySpeechEvaluator parameterForKey:[IFlySpeechConstant RESULT_ENCODING]]isEqualToString:@"utf-8"];
        NSString* strResults=nil;
        if(isUTF8){
            strResults=[[NSString alloc] initWithBytes:chResult length:[results length] encoding:NSUTF8StringEncoding];
        }else{
            NSLog(@"result encoding: gb2312");
            NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
            strResults=[[NSString alloc] initWithBytes:chResult length:[results length] encoding:encoding];
        }
        if(strResults){
            showText = [showText stringByAppendingString:strResults];
        }
        
        if(isLast){
        
            if(self.completionHandlers!=nil){
                self.completionHandlers(showText);
            }
        }
    }
    else{
        if(isLast){
            NSLog(@"result%@", NSLocalizedString(@"M_ISE_Msg", nil));
        }
        
    }
    
}


#pragma mark - IFlyPcmRecorderDelegate

- (void) onIFlyRecorderBuffer: (const void *)buffer bufferSize:(int)size
{
    NSData *audioBuffer = [NSData dataWithBytes:buffer length:size];
    
    int ret = [self.iFlySpeechEvaluator writeAudio:audioBuffer];
    if (!ret)
    {
        [self.iFlySpeechEvaluator stopListening];
    }
}

- (void) onIFlyRecorderError:(IFlyPcmRecorder*)recoder theError:(int) error
{
    
}

//range from 0 to 30
- (void) onIFlyRecorderVolumeChanged:(int) power
{
    
}




-(void) addRecognizeResultHandler:(completionHandler)handler
{
    self.completionHandlers=handler;
}

@end
